/************************************************************************

								Heroes III
					  Copyright 1998, The 3DO Company

	------------------------------------------------------------------
  							    diff.cpp

	$Header: /Heroes3Exp2/Game/diff.cpp 1     9/13/99 10:49a Drichey $

	$NoKeywords: $

 ************************************************************************/

#include "precompiled.h"
#include "diff.h"


t_diff::t_diff()
{}

t_diff::~t_diff()
{}

void t_diff::apply (	std::streambuf & stream_init  ,
						std::streambuf & stream_final ,
						std::streambuf & diff_stream )
{
	//PDL::
	// -takes 2 streams and runs a diff algorithm on blocks of of them finding 
	//		different blocks and putting them in the diff stream.
}

/*
#define MIN_SAME_SIZE		16		// min of 16 bytes needed to be considered same...
#define SCAN_SIZE			64		// scan ahead 64 bytes 


//---------------------------------------------------------------------------
// This code is used to make and read save game diff files.  Save game diff
// files are used when transfering turn data from player to player.....
// these diff files should be considerably smaller than sending the full 
// save game...............
//---------------------------------------------------------------------------


class CDiffHeader
{
public:
	int		m_numBytes;
	int		m_oldNumBytes;
	bool	m_copy;
	
	CDiffHeader (int numBytes, bool copy, int oldNumBytes)
	{
		m_numBytes		= numBytes;
		m_oldNumBytes	= oldNumBytes;
		m_copy			= copy;
	}
};

CDiffFile::CDiffFile ()
{
	assert ( 0 );	// This class is only casted... it is never instantiated on its own.
}

BYTE *CDiffFile::GetData ()
{
	return ((BYTE*)this)+sizeof(saveGameSize);
}

void *CDiffFile::Apply (BYTE *oldSaveGame, int oldSaveGameSize)
{
	BYTE	*newSaveGame	= new BYTE [ saveGameSize ];
	BYTE	*diffData		= GetData();
	int		newOffset		= 0;
	int		diffOffset		= 0;
	int		oldOffset		= 0;

	CDiffHeader		*pHeader;	

	while ( newOffset<saveGameSize )
	{
		pHeader = (CDiffHeader*)(diffData+diffOffset);

		if ( pHeader->m_copy )
		{
//			logFile.Log ( "Copying from diff: oldOffset[%d] newOffset[%d] size=%d", oldOffset,newOffset,pHeader->m_numBytes );

			diffOffset += sizeof (CDiffHeader);

			memcpy (newSaveGame+newOffset,diffData+diffOffset,pHeader->m_numBytes);

			diffOffset	+= pHeader->m_numBytes;
			newOffset	+= pHeader->m_numBytes;
			oldOffset	+= pHeader->m_oldNumBytes;
		}
		else
		{
			memcpy (newSaveGame+newOffset,oldSaveGame+oldOffset,pHeader->m_numBytes);

//			logFile.Log ( "Copying from old: oldOffset[%d] newOffset[%d] size=%d", oldOffset,newOffset,pHeader->m_numBytes );

			diffOffset	+= sizeof (CDiffHeader);
			newOffset	+= pHeader->m_numBytes;
			oldOffset	+= pHeader->m_numBytes;
		}

	}

	assert ( newOffset==saveGameSize );

	return newSaveGame;
}


CDiffMaker::CDiffMaker (BYTE *oldData, int oldSize, BYTE *newData, int newSize)
{
	m_oldData		= oldData;
	m_newData		= newData;
	m_oldSize		= oldSize;
	m_newSize		= newSize;
}

int CDiffMaker::CountSameBytes (int oldOffset, int newOffset)
{
	int		count=0;

	while ( m_oldData[oldOffset+count]==m_newData[newOffset+count] )
	{
		if ( oldOffset+count >= m_oldSize )
			break;
		
		if ( newOffset+count >= m_newSize )
			break;

		count++;
	}

	return count;
}

bool CDiffMaker::FindNextSame (int oldOffset, int newOffset, int &oldCount, int &newCount)
{
	oldCount	= 1;
	newCount	= 1;

	oldOffset	+= 1;
	newOffset	+= 1;

	while ( 1 )
	{
		for (int i=0;i<SCAN_SIZE;i++)
		{
			for (int j=0;j<SCAN_SIZE;j++)
			{
				if ( oldOffset+j+MIN_SAME_SIZE >= m_oldSize )
					return false;

				if ( newOffset+i+MIN_SAME_SIZE >= m_newSize )
					return false;

				if ( memcmp (m_newData+newOffset+i, m_oldData+oldOffset+j, MIN_SAME_SIZE)==0 )
				{
					// we've found some sameness!!  
					newCount	+= i;
					oldCount	+= j;
					return true;
				}
			}
		}

		oldOffset	+= SCAN_SIZE;
		newOffset	+= SCAN_SIZE;

		oldCount	+= SCAN_SIZE;
		newCount	+= SCAN_SIZE;
	}

	return false;
}


CDiffFile *CDiffMaker::MakeDiff (DWORD &diffSize)
{
	int		oldOffset=0;
	int		newOffset=0;
	int		diffOffset=0;
	int		size;

	diffSize	= 0;

	BYTE	*diffData = new BYTE [ max(m_oldSize,m_newSize)+5000 ];

	// make room for the diff size
	diffOffset	+= sizeof (DWORD);

	while ( 1 )
	{
		size	= CountSameBytes (oldOffset,newOffset);

		if ( size==0 )
		{
			// we've run into a different byte or section of bytes...

			int		oldCount=0;
			int		newCount=0;

			if ( FindNextSame (oldOffset,newOffset,oldCount,newCount) )
			{
				// we found another same area...  Now copy the different and continue..

				CDiffHeader		diffHeader ( newCount, true, oldCount );

				memcpy ( diffData+diffOffset, &diffHeader, sizeof (diffHeader) );
				diffOffset	+= sizeof (diffHeader);

				// copy the data

//				logFile.Log ("Copy from diff: oldOffset [%d] newOffset[%d], amount=%d", oldOffset,newOffset,newCount);

				memcpy (diffData+diffOffset, m_newData+newOffset, newCount);

				diffOffset		+= newCount;
				newOffset		+= newCount;
				oldOffset		+= oldCount;
			}
			else
			{
				// I guess the rest of the data is different and we're done...
				CDiffHeader		diffHeader ( m_newSize - newOffset, true, 0 );

				memcpy ( diffData+diffOffset, &diffHeader, sizeof (diffHeader) );
				diffOffset	+= sizeof (diffHeader);

				// now copy the data...
				memcpy ( diffData+diffOffset, m_newData+newOffset, m_newSize-newOffset );

				diffOffset	+= (m_newSize-newOffset);
				break;
			}
		}
		else
		{
			// skip same bytes...
			CDiffHeader		diffHeader (size, false, 0);

			memcpy ( diffData+diffOffset, &diffHeader, sizeof (diffHeader) );
			diffOffset	+= sizeof (diffHeader);

//			logFile.Log ( "Copy From Save oldOffset[%d] newOffset[%d], amount=%d", oldOffset,newOffset,size );

			oldOffset	+= size;
			newOffset	+= size;

		}
	}

	diffSize			= diffOffset;

	CDiffFile	*pDiffFile = (CDiffFile*)diffData;

	pDiffFile->saveGameSize	= m_newSize;

	return pDiffFile;
}

*/
